home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJLSR111.ZIP / libsrc / pc / src / gppconio.sav < prev    next >
Text File  |  1993-10-09  |  18KB  |  724 lines

  1. /**********************************************************************
  2.  *  
  3.  *  NAME:           gppconio.c
  4.  *  
  5.  *  DESCRIPTION:    simulate Borland text video funcs for GNU C++
  6.  *  
  7.  *  copyright (c) 1991 J. Alan Eldridge
  8.  * 
  9.  *  M O D I F I C A T I O N   H I S T O R Y
  10.  *
  11.  *  when        who                 what
  12.  *  -------------------------------------------------------------------
  13.  *  10/27/91    J. Alan Eldridge    created
  14.  *  01/06/92    D. Buerssner        make it work with extended characters
  15.  * (buers@dg1.chemie.uni-konstanz.de) speed-up of cputs
  16.  *                                  some missing brackets in VIDADDR
  17.  *                                  don't need scrollwindow anymore
  18.  *  07/15/93    D. Buerssner        take care of cursor tracking
  19.  *                                    txinfo.curx and txinfo.cury
  20.  *                                  fill in missing functionality
  21.  *                                    - textmode
  22.  *                                    - cscanf
  23.  *                                    - cgets
  24.  *                                    - getch and ungetch
  25.  *                                    - _setcursortype
  26.  *                                    - kbhit 
  27.  *                                  (hpefully) proper initialization of
  28.  *                                    txinfo.normattrib and txinfo.attribute  
  29.  *                                  gotoxy(1,1) in clrscr (bug introduced
  30.  *                                    by my previous patches)
  31.  *                                  gotoxy(1,1) in window
  32.  *                                  take care of BELL and BACKSPACE
  33.  *                                    in putch and cputs
  34.  *                                  take care of blinking bit in textcolor
  35.  *                                    and textbackground
  36.  *                                  declare (and ignore) directvideo 
  37.  *********************************************************************/
  38.  
  39. #include    <stdlib.h>
  40. #include    <stdio.h>
  41. #include    <stdarg.h>
  42. #include    <dos.h>
  43. #include    <pc.h>
  44. #include    "gppconio.h"
  45.  
  46. int directvideo = 1;  /* We ignore this */
  47.  
  48. static void setcursor(unsigned int shape);
  49. static int getvideomode(void);
  50. static void bell(void);
  51. static int get_screenattrib(void);
  52. static int isEGA(void);
  53. static int _scan_getche(FILE *fp);
  54. static int _scan_ungetch(int c, FILE *fp);
  55.  
  56. #define DBGGTINFO   0
  57.  
  58. static struct text_info txinfo;
  59. static int ungot_char;
  60. static int char_avail = 0;
  61.  
  62. #define VIDADDR(r,c) (ScreenPrimary + ((r) * txinfo.screenwidth) + (c))
  63.  
  64. int puttext(int c, int r, int c2, int r2, void *buf)
  65. {
  66.   int     c0;
  67.   short   *pvch = (short *)buf;
  68.   /* we should check for valid parameters, and maybe return 0 */
  69.   r--, r2--, c--, c2--;
  70.   for (c0 = c; r <= r2; r++) 
  71.     for (c = c0; c <= c2; c++)
  72.       *VIDADDR(r,c) = *pvch++;
  73.   return 1;
  74. }
  75.  
  76. int gettext(int c, int r, int c2, int r2, void *buf)
  77. {
  78.   int     c0;
  79.   short   *pvch = (short *)buf;
  80.   /* we should check for valid parameters, and maybe return 0 */
  81.   r--, r2--, c--, c2--;
  82.   for (c0 = c; r <= r2; r++) {
  83.     for (c = c0; c <= c2; c++)
  84.       *pvch++ = *VIDADDR(r,c);
  85.   }
  86.   return 1;
  87. }
  88.         
  89. void gotoxy(int col, int row)
  90. {
  91.   ScreenSetCursor(row + txinfo.wintop - 2, col + txinfo.winleft - 2);
  92.   txinfo.curx = col;
  93.   txinfo.cury = row;
  94. }
  95.  
  96. int wherex(void)
  97. {
  98.   int row, col;
  99.   
  100.   ScreenGetCursor(&row, &col);
  101.   
  102.   return col - txinfo.winleft + 2;
  103. }
  104.     
  105. int wherey(void)
  106. {
  107.   int row, col;
  108.   
  109.   ScreenGetCursor(&row, &col);
  110.   
  111.   return row - txinfo.wintop + 2;
  112. }
  113.  
  114. void textmode(int mode)
  115. {
  116.     union REGS regs;
  117.     int mode_to_set = mode;
  118.     if (mode == LASTMODE)
  119.         mode = mode_to_set = txinfo.currmode;
  120.     if (mode == C4350)
  121.         /* 
  122.          * just set mode 3 and load 8x8 font, idea taken 
  123.          * (and code translated from Assembler to C)
  124.          * form Csaba Biegels stdvga.asm
  125.          */
  126.         mode_to_set = 0x03;  
  127.     regs.h.ah = 0x00; /* set mode */
  128.     regs.h.al = mode_to_set;
  129.     int86(0x10, ®s, ®s);
  130.     if (mode == C80 || mode == BW80 || mode == C4350)
  131.     {
  132.         if (isEGA())
  133.         {
  134.             /* 
  135.              * enable cursor size emulation, see Ralf Browns
  136.              * interrupt list
  137.              */
  138.             regs.h.ah = 0x12;
  139.             regs.h.bl = 0x34;
  140.             regs.h.al = 0x00; /* 0: enable (1: disable) */
  141.             int86(0x10, ®s, ®s);
  142.     }
  143.     }
  144.     if (mode == C4350)
  145.     {
  146.         if (!isEGA())
  147.             return;
  148.         /* load 8x8 font */
  149.         regs.x.ax = 0x1112;         
  150.         regs.x.bx = 0;
  151.         int86(0x10, ®s, ®s);
  152.     }
  153. /*    _setcursortype(_NORMALCURSOR); */
  154.     /* reinitialize txinfo structure to take into account new mode */
  155.     gppconio_init();
  156. #if 0
  157.     /*
  158.      * For mode C4350 the screen is not cleared on my OAK-VGA.
  159.      * Should we clear it here? TURBOC doesn't so we don't bother either.
  160.      */
  161.     clrscr();
  162. #endif
  163. }    
  164.     
  165. void textattr(int attr)
  166. {
  167.   txinfo.attribute = ScreenAttrib = (unsigned char)attr;
  168. }
  169.  
  170. void textcolor(int color)
  171. {
  172.   /* strip blinking (highest) bit and textcolor */
  173.   ScreenAttrib &= 0x70; /* strip blinking (highest) bit and textcolor */
  174.   txinfo.attribute=(ScreenAttrib |= (color & 0x8f));
  175. }
  176.  
  177. void textbackground(int color)
  178. {
  179.   /* strip background color, keep blinking bit */
  180.   ScreenAttrib &= 0x8f; 
  181.   /* high intensity background colors (>7) are not allowed 
  182.      so we strip 0x08 bit (and higher bits) of color */
  183.   txinfo.attribute=(ScreenAttrib |= ((color & 0x07) << 4));
  184. }
  185.  
  186. void highvideo(void)
  187. {
  188.   txinfo.attribute=(ScreenAttrib |= 0x08);
  189. }
  190.  
  191. void lowvideo(void)
  192. {
  193.   txinfo.attribute=(ScreenAttrib &= 0x07);
  194. }
  195.  
  196. void normvideo(void)
  197. {
  198.   txinfo.attribute = ScreenAttrib = txinfo.normattr;
  199. }
  200.  
  201. void _setcursortype(int type)
  202. {
  203.     unsigned cursor_shape;
  204.     switch (type)
  205.     {
  206.         case _NOCURSOR:
  207.             cursor_shape = 0x0700;
  208.             break;
  209.         case _SOLIDCURSOR:
  210.             cursor_shape = 0x0007;
  211.             break;
  212. /*      case _NORMALCURSOR: */
  213.         default:
  214.             cursor_shape = 0x0607;
  215.             break;
  216.     }
  217.     setcursor(cursor_shape);
  218. }        
  219.  
  220. static void setcursor(unsigned int cursor_shape)
  221. /* Sets the shape of the cursor */
  222. {
  223.     union REGS      reg;
  224.  
  225.     reg.h.ah = 1;
  226.     reg.x.cx = cursor_shape;
  227.     int86(0x10, ®, ®);
  228. }                /* setcursor */
  229.  
  230. static void getwincursor(int *row, int *col)
  231. {
  232.   ScreenGetCursor(row, col);
  233. }
  234.  
  235. void clreol(void)
  236. {
  237.   short   image[ 256 ];
  238.   short   val = ' ' | (ScreenAttrib << 8);
  239.   int     c, row, col, ncols;
  240.   
  241.   getwincursor(&row, &col);
  242.   ncols = txinfo.winright - col;
  243.   
  244.   for (c = 0; c < ncols; c++)
  245.     image[ c ] = val;
  246.   
  247.   puttext(col + 1, row + 1, txinfo.winright, row + 1, image);
  248. }
  249.  
  250. static void fillrow(int row, int left, int right, int fill)
  251. {
  252.   int col;
  253.   
  254.   for (col = left; col <= right; col++)
  255.     *VIDADDR(row, col) = fill;
  256. }
  257.  
  258. void clrscr(void)
  259. {
  260.   int row, col;
  261.   int c =  ' ' | (ScreenAttrib << 8);
  262.   for (row=txinfo.wintop-1; row < txinfo.winbottom; row++)
  263.     for (col=txinfo.winleft-1; col < txinfo.winright; col++)
  264.       *VIDADDR(row,col) = c;
  265.   gotoxy(1, 1);
  266. }
  267.  
  268. int putch(int c)
  269. {
  270.   int     row, col;
  271.   
  272.   ScreenGetCursor(&row, &col);
  273.   
  274.   /*  first, handle the character */
  275.   if (c == '\n')
  276.     {
  277.       row++;
  278.     }
  279.   else if (c == '\r')
  280.     {
  281.       col = txinfo.winleft - 1;
  282.     }
  283.   else if (c == '\b')
  284.   {
  285.       if (col > txinfo.winleft - 1)
  286.           col--;  
  287.       else if (row > txinfo.wintop -1)
  288.       {
  289.           /* 
  290.            * Turbo-C ignores this case; we are smarter.
  291.            */
  292.           row--;
  293.           col = txinfo.winright-1;
  294.       }  
  295.   }      
  296.   else if (c == 0x07)
  297.     bell();
  298.   else {
  299.     short   val = c | (ScreenAttrib << 8);
  300.     /* puttext(col + 1, row + 1, col + 1, row + 1, &val); */
  301.     *VIDADDR(row,col) = val;
  302.     col++;
  303.   }
  304.   
  305.   /* now, readjust the window     */
  306.   
  307.   if (col >= txinfo.winright) {
  308.     col = txinfo.winleft - 1;
  309.     row++;
  310.   }
  311.   
  312.   if (row >= txinfo.winbottom) {
  313.     /* scrollwin(0, txinfo.winbottom - txinfo.wintop, 1); */
  314.     ScreenSetCursor(txinfo.wintop-1,0);
  315.     delline();
  316.     row--;
  317.   }
  318.   
  319.   ScreenSetCursor(row, col);
  320.   txinfo.cury = row - txinfo.wintop + 2;
  321.   txinfo.curx = col - txinfo.winleft + 2;
  322.   return c;
  323. }
  324.  
  325. int getche(void)
  326. {
  327.   if (char_avail)
  328.     /*
  329.      * We don't know, wether the ungot char was already echoed
  330.      * we assume yes (for example in cscanf, probably the only
  331.      * place where ungetch is ever called.
  332.      * There is no way to check for this really, because
  333.      * ungetch could have been called with a character that
  334.      * hasn't been got by a conio function.
  335.      * We don't echo again.
  336.      */ 
  337.     return(getch());
  338.   return (putch(getch()));
  339. }
  340.  
  341. int getch(void)
  342. {
  343.     union REGS regs;
  344.     int c;
  345.     if (char_avail)
  346.     {
  347.         c = ungot_char;
  348.         char_avail = 0;
  349.     }
  350.     else
  351.     {
  352.         regs.x.ax = 0x0700;
  353.         int86(0x21, ®s, ®s);
  354.         c = regs.h.al;
  355.     }
  356.     return(c);
  357. }
  358.  
  359. int ungetch(int c)
  360. {
  361.     if (char_avail)
  362.         return(EOF);
  363.     ungot_char = c;
  364.     char_avail = 1;
  365.     return(c);
  366. }
  367.  
  368. /* 
  369.  * kbhit from libc in libsrc/c/dos/kbhit.s doesn't check
  370.  * for ungotten chars, so we have to provide a new one
  371.  * Don't call it kbhit, rather use a new name (_conio_kbhit)
  372.  * and do a #define kbhit _conio_kbhit in gppconio.h.
  373.  * The old kbhit still can be used if gppconio.h
  374.  * is not included of after #undef kbhit
  375.  * If you don't use ungetch (directly or indirectly by cscanf)
  376.  * both kbhit and _conio_kbhit are the same.
  377.  * So this shouldn't cause any trouble with previously written
  378.  * source, because ungetch wasn't available.
  379.  * The only problem might be, if anybody just included gppconio.h
  380.  * and has not linked with libpc, (I can't think of a good reason
  381.  * for this). This will result a link error (undefined symbol _conio_kbhit).
  382.  */
  383.  
  384. #undef kbhit  /* want to be able to call kbhit from libc */
  385.  
  386. int _conio_kbhit(void)
  387. {
  388.     if (char_avail)
  389.         return(1);
  390.     else
  391.         return(kbhit());
  392. }    
  393.  
  394. /*
  395.  * The next two functions are needed by cscanf
  396.  */
  397. static int _scan_getche(FILE *fp)
  398. {
  399.     return(getche());
  400. }
  401.  
  402. static int _scan_ungetch(int c, FILE *fp)
  403. {
  404.     return(ungetch(c));
  405. }
  406.  
  407.  
  408. void insline(void)
  409. {
  410.   int row, col, left, right, nbytes, bot, fill;
  411.   ScreenGetCursor(&row, &col);
  412.   left = txinfo.winleft - 1;
  413.   right = txinfo.winright - 1;
  414.   nbytes = (right-left+1)*2;
  415.   bot = txinfo.winbottom-1;
  416.   fill = ' ' | (ScreenAttrib << 8);
  417.   while(bot > row+1)
  418.     {
  419.       memcpy(VIDADDR(bot,left), VIDADDR(bot-1,left), nbytes);
  420.       bot--;
  421.     }
  422.   if (row < txinfo.winbottom -1)
  423.     {
  424.       fillrow(row+1,left,right,fill);
  425.     }
  426. }
  427.  
  428.  
  429. void delline(void)
  430. {
  431.   int row, col, left, right, nbytes, bot, fill;
  432.   ScreenGetCursor(&row, &col);
  433.   left = txinfo.winleft - 1;
  434.   right = txinfo.winright - 1;
  435.   nbytes = (right-left+1)*2;
  436.   bot = txinfo.winbottom-1;
  437.   fill = ' ' | (ScreenAttrib << 8);
  438.   while(row < bot)
  439.     {
  440.       memcpy(VIDADDR(row,left), VIDADDR(row+1,left), nbytes);
  441.       row++;
  442.     }
  443.   fillrow(bot,left,right,fill);
  444. }
  445.  
  446.  
  447. void window(int left, int top, int right, int bottom)
  448. {
  449.   if (top < 1 || left < 1 || right > txinfo.screenwidth ||
  450.       bottom > txinfo.screenheight)
  451.     return;
  452.   
  453.   txinfo.wintop = top;
  454.   txinfo.winleft = left;
  455.   txinfo.winright = right;
  456.   txinfo.winbottom = bottom;
  457.   gotoxy(1,1);
  458. }
  459.  
  460.  
  461. int cputs(const char *s)
  462. {
  463.   int     row, col,c;
  464.   const unsigned char *ss = (const unsigned char *)s;
  465.   short *viaddr;
  466.   short sa = ScreenAttrib << 8;
  467.   ScreenGetCursor(&row, &col);
  468.   viaddr = (short *)VIDADDR(row,col);
  469.   /* 
  470.    * Instead of just calling putch; we do everything by hand here,
  471.    * This is much faster. We don't move the cursor after each character,
  472.    * only after the whole string is written, because ScreenSetCursor
  473.    * needs to long because of switching to real mode needed with djgpp. 
  474.    * You won't recognize the difference.
  475.    */
  476.   while (c = *ss++)
  477.     {
  478.       /*  first, handle the character */
  479.       if (c == '\n')
  480.     {
  481.       row++;
  482.       viaddr += txinfo.screenwidth;
  483.     }
  484.       else if (c == '\r')
  485.     {
  486.       col = txinfo.winleft - 1;
  487.       viaddr = (short *)VIDADDR(row,col);
  488.     }
  489.       else if (c == '\b')
  490.         {
  491.           if (col > txinfo.winleft-1) 
  492.           {
  493.               col--;
  494.               viaddr--;
  495.           }
  496.           else if (row > txinfo.wintop -1)
  497.           {
  498.               /* 
  499.                * Turbo-C ignores this case. We want to be able to
  500.                * edit strings with backspace in gets after
  501.                * a linefeed, so we are smarter
  502.                */
  503.               row--;
  504.               col = txinfo.winright-1;
  505.               viaddr = (short *)VIDADDR(row,col);
  506.           }
  507.         }
  508.       else if (c == 0x07)
  509.           bell();
  510.       else {
  511.     *viaddr++ = c | sa;
  512.     col++;
  513.       }
  514.       
  515.       /* now, readjust the window     */
  516.       
  517.       if (col >= txinfo.winright) {
  518.     col = txinfo.winleft - 1;
  519.     row++;
  520.     viaddr = (short *)VIDADDR(row,col);
  521.       }
  522.       
  523.       if (row >= txinfo.winbottom) {
  524.     ScreenSetCursor(txinfo.wintop-1,0); /* goto first line in window */
  525.     delline();                          /* and delete it */
  526.     row--;
  527.     viaddr -= txinfo.screenwidth;
  528.       }
  529.     }
  530.   
  531.   ScreenSetCursor(row, col);
  532.   txinfo.cury = row - txinfo.wintop + 2;
  533.   txinfo.curx = col - txinfo.winleft + 2;
  534.   return(*(--ss));
  535. }
  536.  
  537.  
  538. int cprintf(const char *fmt, ...)
  539. {
  540.   int     cnt;
  541.   char    buf[ 2048 ]; /* this is buggy, because buffer might be too small. */
  542.   va_list ap;
  543.   
  544.   va_start(ap, fmt);
  545.   cnt = vsprintf(buf, fmt, ap);
  546.   va_end(ap);
  547.   
  548.   cputs(buf);
  549.   return cnt;
  550. }
  551.  
  552. char *cgets(char *string)
  553. {
  554.     unsigned len = 0;
  555.     unsigned int maxlen_wanted;
  556.     char *sp;
  557.     int c;
  558.     /*
  559.      * Be smart and check for NULL pointer.
  560.      * Don't know wether TURBOC does this.
  561.      */
  562.     if (!string)
  563.         return(NULL);
  564.     maxlen_wanted = (unsigned int)((unsigned char)string[0]);
  565.     sp = &(string[2]);
  566.     /* 
  567.      * Should the string be shorter maxlen_wanted including or excluding
  568.      * the trailing '\0' ? We don't take any risk.
  569.      */
  570.     while(len < maxlen_wanted-1)
  571.     {
  572.         c=getch();
  573.         /*
  574.          * shold we check for backspace here?
  575.          * TURBOC does (just checked) but doesn't in cscanf (thats harder
  576.          * or even impossible). We do the same.
  577.          */
  578.         if (c == '\b')
  579.         {
  580.             if (len > 0)
  581.             {
  582.                cputs("\b \b"); /* go back, clear char on screen with space
  583.                                   and go back again */
  584.                len--;
  585.                sp[len] = '\0'; /* clear the character in the string */
  586.             }
  587.         }
  588.         else if (c == '\r')
  589.         {
  590.             sp[len] = '\0';
  591.             break;
  592.         }
  593.         else if (c == 0)
  594.         {
  595.             /* special character ends input */
  596.             sp[len] = '\0';
  597.             ungetch(c); /* keep the char for later processing */
  598.             break;
  599.         }
  600.         else
  601.         {
  602.            sp[len] = putch(c);
  603.            len++;
  604.         }
  605.      }
  606.      sp[maxlen_wanted-1] = '\0';
  607.      string[1] = (char)((unsigned char)len);
  608.      return(sp);   
  609. }    
  610.  
  611. int cscanf(const char *fmt, ...)
  612. {
  613.     return(_doscan_low(NULL, _scan_getche, _scan_ungetch, 
  614.                        fmt, (void **)((&fmt)+1)));
  615. }
  616.  
  617. int movetext(int left, int top, int right, int bottom, int dleft, int dtop)
  618. {
  619.   char    *buf = malloc((right - left + 1) * (bottom - top + 1) * 2);
  620.   
  621.   if (!buf)
  622.     return 0;
  623.   
  624.   gettext(left, top, right, bottom, buf);
  625.   puttext(dleft, dtop, dleft + right - left, dtop + bottom - top, buf);
  626.   free(buf);
  627.   return 1;
  628. }
  629.  
  630. static void _gettextinfo(struct text_info *t)
  631. {
  632.   int row, col;
  633.   
  634.   t->winleft = t->wintop = 1;
  635.   t->winright = t->screenwidth = ScreenCols();
  636.   t->winbottom = t->screenheight = ScreenRows();
  637.   ScreenAttrib = t->attribute = t->normattr = get_screenattrib();
  638.   t->currmode = getvideomode();
  639.   ScreenGetCursor(&row, &col);
  640.   t->curx = col+1;
  641.   t->cury = row+1;
  642. #if DBGGTINFO
  643.   printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft,
  644.      t->winright,t->wintop,t->winbottom);
  645.   printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n",
  646.      t->screenheight, t->screenwidth, t->normattr, t->currmode,
  647.      t->curx, t->cury);
  648. #endif
  649. }
  650.  
  651. void gettextinfo(struct text_info *t)
  652. {
  653.   *t = txinfo; 
  654. #if DBGGTINFO
  655.   printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft,
  656.      t->winright,t->wintop,t->winbottom);
  657.   printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n",
  658.      t->screenheight, t->screenwidth, t->normattr, t->currmode,
  659.      t->curx, t->cury);
  660. #endif
  661. }
  662.  
  663. static int
  664. getvideomode(void)
  665. {
  666.     int mode = ScreenMode();
  667.     /* 
  668.      * in mode C80 we might have loaded a different font
  669.      */
  670.     if (mode == C80)
  671.         if (ScreenRows() > 25)
  672.            mode = C4350;
  673.     return(mode);
  674. }
  675.     
  676.  
  677. static void bell(void)
  678. {
  679.     union REGS regs;
  680.     regs.h.ah = 0x0e; /* write */
  681.     regs.h.al = 0x07; /* bell */
  682.     int86(0x10, ®s, ®s);
  683. }
  684.  
  685. static int 
  686. get_screenattrib(void)
  687. {
  688.     union REGS regs;
  689.     regs.h.ah = 0x08; /* read character and attribute */
  690.     regs.h.bh = 0;    /* video page 0 */
  691.     int86(0x10, ®s, ®s);
  692.     return(regs.h.ah & 0x7f); /* strip highest (BLINK) bit */
  693. }
  694.  
  695. /* check if we have at least EGA (idea form Ralf Browns interrupt list) */
  696. static int
  697. isEGA(void)
  698. {
  699.     union REGS regs;
  700.     regs.h.ah = 0x12;
  701.     regs.h.bl = 0x10;
  702.     regs.h.bh = 0xff;
  703.     int86(0x10, ®s, ®s);
  704.     return(regs.h.bh != 0xff);
  705. }
  706.  
  707.  
  708. extern int _gppconio_init;
  709.  
  710. void gppconio_init(void)
  711. {
  712.     static int oldattrib =  -1;
  713.     if (oldattrib == -1)
  714.         oldattrib = get_screenattrib();   
  715.     _gettextinfo(&txinfo);
  716.     if (txinfo.currmode == 7)    /* MONO */
  717.         ScreenPrimary = (short *)0xe00b0000UL;
  718.     else
  719.     ScreenPrimary = (short *)0xe00b8000UL;
  720.     ScreenAttrib = txinfo.normattr = txinfo.attribute = oldattrib;
  721.     _gppconio_init = 1;
  722. }
  723.  
  724.